/*******************************************************************************
 * Copyright (c) 2005 Koji Hisano <hisano@users.sourceforge.net>
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     Koji Hisano - initial API and implementation
 *******************************************************************************/
package jp.sf.mapswidgets;

import java.util.Arrays;

/**
 * Instances of this class represent the image used to display a marker on the map.
 * <p>
 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon</a>].
 * </p>
 *
 * @see Marker
 */
public final class Icon implements Cloneable {
	private String imageURL;
	private Size imageSize;
	private String shadowImageURL;
	private Size shadowImageSize;
	private Point offsetOfMarker;

	private Point offsetOfInfoWindow;
	private String printImageURL;
	private String printImageURLForMozilla;
	private String printShadowImageURL;
	private String clickAreImageURL;
	private int[] clickArea;
	
	/**
	 * Construct a new instance of this class.
	 */
	public Icon() {
	}
	
	/**
	 * Construct a new instance of this class given the icon.
	 * 
	 * @param copyFrom the base icon
	 */
	public Icon(Icon copyFrom) {
		this.imageURL = copyFrom.imageURL;
		if (copyFrom.imageSize != null) {
			this.imageSize = copyFrom.imageSize.clone();
		}
		this.shadowImageURL = copyFrom.shadowImageURL;
		if (copyFrom.shadowImageSize != null) {
			this.shadowImageSize = copyFrom.shadowImageSize.clone();
		}
		if (copyFrom.offsetOfMarker != null) {
			this.offsetOfMarker = copyFrom.offsetOfMarker.clone();
		}

		if (copyFrom.offsetOfInfoWindow != null) {
			this.offsetOfInfoWindow = copyFrom.offsetOfInfoWindow.clone();
		}
		this.printImageURL = copyFrom.printImageURL;
		this.printImageURLForMozilla = copyFrom.printImageURLForMozilla;
		this.printShadowImageURL = copyFrom.printShadowImageURL;
		this.clickAreImageURL = copyFrom.clickAreImageURL;
		if (copyFrom.clickArea != null) {
			this.clickArea = copyFrom.clickArea.clone();
		}
	}
	
	/**
	 * Construct a new instance of this class given the mandatory values.
	 * 
	 * @param imageURL the icon image URL
	 * @param imageSize the icon image size
	 * @param shadowImageURL the shadow icon image URL
	 * @param shadowImageSize the shadow icon image size
	 * @param offsetOfMarker the offset of the marker
	 */
	public Icon(String imageURL, Size imageSize, String shadowImageURL, Size shadowImageSize, Point offsetOfMarker) {
		this.imageURL = imageURL;
		this.imageSize = imageSize;
		this.shadowImageURL = shadowImageURL;
		this.shadowImageSize = shadowImageSize;
		this.offsetOfMarker = offsetOfMarker;
	}

	/**
	 * Get the image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; image</a>].
	 * </p>
	 * 
	 * @return the image URL
	 */
	public String getImageURL() {
		return imageURL;
	}

	/**
	 * Set the image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; image</a>].
	 * </p>
	 * 
	 * @param imageURL the image URL
	 */
	public void setImageURL(String imageURL) {
		CheckUtils.isNotNull("imageURL", imageURL);
		this.imageURL = imageURL;
	}

	/**
	 * Get the image size.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconSize</a>].
	 * </p>
	 * 
	 * @return the image size
	 */
	public Size getImageSize() {
		return imageSize;
	}

	/**
	 * Set the image size.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconSize</a>].
	 * </p>
	 * 
	 * @param imageSize the image size
	 */
	public void setImageSize(Size imageSize) {
		CheckUtils.isNotNull("imageSize", imageSize);
		this.imageSize = imageSize;
	}

	/**
	 * Get the shadow image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; shadow</a>].
	 * </p>
	 * 
	 * @return the shadow image URL
	 */
	public String getShadowImageURL() {
		return shadowImageURL;
	}

	/**
	 * Set the shadow image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; shadow</a>].
	 * </p>
	 * 
	 * @param shadowImageURL the shadow image URL
	 */
	public void setShadowImageURL(String shadowImageURL) {
		CheckUtils.isNotNull("shadowImageURL", shadowImageURL);
		this.shadowImageURL = shadowImageURL;
	}

	/**
	 * Get the shadow image size.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; shadowSize</a>].
	 * </p>
	 * 
	 * @return the shadow image size
	 */
	public Size getShadowImageSize() {
		return shadowImageSize;
	}

	/**
	 * Set the shadow image size.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; shadowSize</a>].
	 * </p>
	 * 
	 * @param shadowImageSize the shadow image size
	 */
	public void setShadowImageSize(Size shadowImageSize) {
		CheckUtils.isNotNull("shadowImageSize", shadowImageSize);
		this.shadowImageSize = shadowImageSize;
	}

	/**
	 * Get the offset of the marker.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconAnchor</a>].
	 * </p>
	 * 
	 * @return the offset of the marker
	 */
	public Point getOffsetOfMarker() {
		return offsetOfMarker;
	}

	/**
	 * Set the offset of the marker.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconAnchor</a>].
	 * </p>
	 * 
	 * @param offsetOfMarker the offset of the marker
	 */
	public void setOffsetOfMarker(Point offsetOfMarker) {
		CheckUtils.isNotNull("offsetFromMarker", offsetOfMarker);
		this.offsetOfMarker = offsetOfMarker;
	}

	/**
	 * Get the offset of the marker info window.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconWindowAnchor</a>].
	 * </p>
	 * 
	 * @return the offset of the marker info window
	 */
	public Point getOffsetOfInfoWindow() {
		return offsetOfInfoWindow;
	}

	/**
	 * Set the offset of the marker info window.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; iconWindowAnchor</a>].
	 * </p>
	 * 
	 * @param offsetOfInfoWindow the offset of the marker info window
	 */
	public void setOffsetOfInfoWindow(Point offsetOfInfoWindow) {
		this.offsetOfInfoWindow = offsetOfInfoWindow;
	}
	
	/**
	 * Get the print image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; printImage</a>].
	 * </p>
	 * 
	 * @return the print image URL
	 */
	public String getPrintImageURL() {
		return printImageURL;
	}

	/**
	 * Set the print image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; printImage</a>].
	 * </p>
	 * 
	 * @param printImageURL the print image URL
	 */
	public void setPrintImageURL(String printImageURL) {
		this.printImageURL = printImageURL;
	}

	/**
	 * Get the print image URL for Firefox/Mozilla.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; mozPrintImage</a>].
	 * </p>
	 * 
	 * @return the print image URL for Firefox/Mozilla
	 */
	public String getPrintImageURLForMozilla() {
		return printImageURLForMozilla;
	}

	/**
	 * Set the print image URL for Firefox/Mozilla.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; mozPrintImage</a>].
	 * </p>
	 * 
	 * @param printImageURLForMozilla the print image URL for Firefox/Mozilla
	 */
	public void setPrintImageURLForMozilla(String printImageURLForMozilla) {
		this.printImageURLForMozilla = printImageURLForMozilla;
	}

	/**
	 * Get the print shadow image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; printShadow</a>].
	 * </p>
	 * 
	 * @return the print shadow image URL
	 */
	public String getPrintShadowImageURL() {
		return printShadowImageURL;
	}

	/**
	 * Set the print shadow image URL.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; printShadow</a>].
	 * </p>
	 * 
	 * @param printShadowImageURL the print shadow image URL
	 */
	public void setPrintShadowImageURL(String printShadowImageURL) {
		this.printShadowImageURL = printShadowImageURL;
	}

	/**
	 * Get the click area image URL to capture IE click events.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; transparent</a>].
	 * </p>
	 * 
	 * @return the click area image URL
	 */
	public String getClickAreImageURL() {
		return clickAreImageURL;
	}

	/**
	 * Set the click area image URL to capture IE click events.
	 * <p>
	 * This image should be a 24-bit PNG version of the main icon image with 1% opacity, but the same shape and size as the main icon.
	 * </p>
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; transparent</a>].
	 * </p>
	 * 
	 * @param clickAreImageURL the click area image URL
	 */
	public void setClickAreImageURL(String clickAreImageURL) {
		this.clickAreImageURL = clickAreImageURL;
	}

	/**
	 * Get the click area to capture non-IE browsers click events.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; imageMap</a>].
	 * </p>
	 * 
	 * @return the click area
	 */
	public int[] getClickArea() {
		return clickArea;
	}

	/**
	 * Set the click area to capture non-IE browsers click events.
	 * <p>
	 * See Google Maps API documentation [<a href="http://www.google.com/apis/maps/documentation/#GIcon_code_">Class Reference &gt; GIcon &gt; imageMap</a>].
	 * </p>
	 * 
	 * @param clickArea the click area
	 */
	public void setClickArea(int[] clickArea) {
		this.clickArea = clickArea;
	}

	String getExpressionToPrepare() {
		StringBuilder expression = new StringBuilder();
		expression.append("map.icon = new GIcon();");
		CheckUtils.isSetted("imageURL", imageURL, "Icon.setImageURL");
		CheckUtils.isSetted("imageSize", imageSize, "Icon.setImageSize");
		CheckUtils.isSetted("shadowImageURL", shadowImageURL, "Icon.setShadowImageURL");
		CheckUtils.isSetted("shadowImageSize", shadowImageSize, "Icon.setShadowImageSize");
		CheckUtils.isSetted("offsetOfMarker", offsetOfMarker, "Icon.setOffsetOfMarker");
		expression.append(" map.icon.image = '" + imageURL + "';");
		expression.append(" map.icon.iconSize = " + imageSize.getExpression() + ";");
		expression.append(" map.icon.shadow = '" + shadowImageURL + "';");
		expression.append(" map.icon.shadowSize = " + shadowImageSize.getExpression() + ";");
		expression.append(" map.icon.iconAnchor = " + offsetOfMarker.getExpression() + ";");
		if (offsetOfInfoWindow != null) {
			expression.append(" map.icon.infoWindowAnchor = " + offsetOfInfoWindow.getExpression() + ";");
		}
		if (printImageURL != null) {
			expression.append(" map.icon.printImage = " + printImageURL + ";");
		}
		if (printImageURLForMozilla != null) {
			expression.append(" map.icon.mozPrintImage = " + printImageURLForMozilla + ";");
		}
		if (printShadowImageURL != null) {
			expression.append(" map.icon.printShadow = " + printShadowImageURL + ";");
		}
		if (clickAreImageURL != null) {
			expression.append(" map.icon.transparent = " + clickAreImageURL + ";");
		}
		if (clickArea != null) {
			expression.append(" map.icon.imageMap = " + Arrays.toString(clickArea) + ";");
		}
		return expression.toString();
	}
}